﻿// -------------------------------------------------------------------------
//    @FileName         :    NFWelfareConfOne.cpp
//    @Author           :    gaoyi
//    @Date             :    2025-06-30
//    @Email			:    445267987@qq.com
//    @Module           :    NFWelfareConfOne
//
// -------------------------------------------------------------------------

#include "NFWelfareConfOne.h"

#include "DescStore/WelfareDesc.h"
#include "DescStore/WelfareNodeDesc.h"
#include "NFComm/NFCore/NFCommon.h"


NFWelfareConfOne::NFWelfareConfOne()
{
    if (EN_OBJ_MODE_INIT == NFShmMgr::Instance()->GetCreateMode())
    {
        CreateInit();
    }
    else
    {
        ResumeInit();
    }
}

NFWelfareConfOne::~NFWelfareConfOne()
{
}

int NFWelfareConfOne::CreateInit()
{
    return 0;
}

int NFWelfareConfOne::ResumeInit()
{
    return 0;
}

void NFWelfareConfOne::Reset()
{
    m_confOne.Init();
}

const E_WelfareNode* NFWelfareConfOne::FindNodeByNodeID(uint32_t dwNodeId) const
{
    auto iter = m_confOne.m_astWelfareNodeDesc.find(dwNodeId);
    if (iter != m_confOne.m_astWelfareNodeDesc.end())
    {
        return &iter->second;
    }
    return nullptr;
}

int NFWelfareConfOne::CheckAndCalcConf(uint32_t dwGameOpenDayBeginUnixSec, bool bIsIdIp, int iWorldId)
{
    int iRetCode = 0;

    LOG_INFO(0, "GameOpenDayBeginUnixSec:{}:{}", dwGameOpenDayBeginUnixSec, NFTimeUtility::DateTimeToStr(dwGameOpenDayBeginUnixSec));

    if (m_confOne.m_stWelfareDesc.m_astServerOpenUnixTimeRange.size() > 0)
    {
        iRetCode = CheckAndSetOpenTimeConf(iWorldId, bIsIdIp);
        CHECK_ERR(0, iRetCode, "CheckAndSetOpenTimeConf(iWorldId:{} bIsIdIp:{})", iWorldId, bIsIdIp);
    }

    if (m_confOne.m_stWelfareDesc.m_stSvrOpenTimeBefore.m_szTime_t == 0)
    {
        m_confOne.m_stWelfareDesc.m_stSvrOpenTimeBefore.m_szTime_t = std::numeric_limits<uint32_t>::max();
    }

    iRetCode = CheckAndCalcOpenTimeRange(m_confOne.m_stWelfareDesc.m_openUnixTimeRange, m_confOne.m_stWelfareDesc.m_openDayGameSvrOpenDay, dwGameOpenDayBeginUnixSec, bIsIdIp, m_confOne.m_stWelfareDesc.m_startTimeGameSvrOpenDay, m_confOne.m_stWelfareDesc.m_endTimeGameSvrOpenDay,
                                         m_confOne.m_stWelfareDesc.m_openTimeGameSvrOpenDayAdjustType, m_confOne.m_stWelfareDesc.m_endTimeGameSvrOpenDayAdjustType);
    CHECK_ERR(0, iRetCode, "CheckAndCalcOpenTimeRange failed");

    iRetCode = CheckAndCalcShowTimeRange(m_confOne.m_stWelfareDesc.m_showUnixTimeRange, m_confOne.m_stWelfareDesc.m_openUnixTimeRange, bIsIdIp);
    CHECK_ERR(0, iRetCode, "CheckAndCalcShowTimeRange failed");

    iRetCode = CalcCanComplete();

    return 0;
}

bool NFWelfareConfOne::IsSkipAndDirSetCanCompleteTrue() const
{
    return false;
}

int NFWelfareConfOne::CalcCanComplete()
{
    if (IsSkipAndDirSetCanCompleteTrue())
    {
        m_confOne.m_bCanComplete = true;
        LOG_DEBUG(0, "skip check calc and set m_bCanComplete=true, m_ullID:{} m_type:{}", m_confOne.m_stWelfareDesc.m_welfareId, m_confOne.m_stWelfareDesc.m_type);
        return 0;
    }

    if (m_confOne.m_stWelfareDesc.m_loopType != WELFARE_LOOP_TYPE_NULL)
    {
        m_confOne.m_bCanComplete = false;
        return 0;
    }

    if (GetNodeNum() == 0)
    {
        m_confOne.m_bCanComplete = false;
        return 0;
    }

    for (auto iter = m_confOne.m_astWelfareNodeDesc.list_begin(); iter != m_confOne.m_astWelfareNodeDesc.list_end(); ++iter)
    {
        auto pNodeDesc = &iter->second;
        if (pNodeDesc->m_loopType != WELFARE_LOOP_TYPE_NULL)
        {
            m_confOne.m_bCanComplete = false;
            return 0;
        }
    }

    m_confOne.m_bCanComplete = true;
    return 0;
}

int NFWelfareConfOne::GetFirstNodeDescByType(int nodeType, const E_WelfareNode*& pNodeDesc) const
{
    pNodeDesc = nullptr;
    for (auto iter = m_confOne.m_astWelfareNodeDesc.list_begin(); iter != m_confOne.m_astWelfareNodeDesc.list_end(); ++iter)
    {
        auto pDesc = &iter->second;
        if (pDesc->m_type == nodeType)
        {
            pNodeDesc = pDesc;
            return 0;
        }
    }

    return -1;
}

int NFWelfareConfOne::CheckAndSetOpenTimeConf(int iWorldId, bool bIsIdIp)
{
    int iRetCode = 0;
    bool bFind = false;
    for (int i = 0; i < (int)m_confOne.m_stWelfareDesc.m_astServerOpenUnixTimeRange.size(); ++i)
    {
        bool bContain = false;
        iRetCode = CheckContainIdWithType(m_confOne.m_stWelfareDesc.m_astServerOpenUnixTimeRange[i].m_szServerIDList.ToString(), iWorldId, bContain);
        CHECK_ERR(0, iRetCode, "CheckContainIDWithType, _welfareDesc.m_astServerOpenUnixTimeRange[{}].m_szServerIDList:{}", i, m_confOne.m_stWelfareDesc.m_astServerOpenUnixTimeRange[i].m_szServerIDList.ToString());
        if (!bContain)
        {
            continue;
        }

        if (bFind)
        {
            CHECK_ERR(0, -1, "you can't repeat world id:{}", iWorldId);
        }

        m_confOne.m_stWelfareDesc.m_openUnixTimeRange = m_confOne.m_stWelfareDesc.m_astServerOpenUnixTimeRange[i].m_stUnixTimeRange;

        bFind = true;
    }

    if (!bFind)
    {
        CHECK_ERR(0, -1, "can't find world id:{}", iWorldId);
    }
    return 0;
}

int NFWelfareConfOne::CheckContainIdWithType(const std::string& strIdRangeList, int iWorldId, bool& bContain)
{
    bContain = false;
    int iRetCode = 0;

    if (strIdRangeList.empty())
    {
        bContain = true;
        return 0;
    }

    if (strIdRangeList.size() < 2)
    {
        CHECK_ERR(0, -1, "invalid strIDRangeList:{}", strIdRangeList);
    }

    int iType = 0;
    if (strIdRangeList[0] == '+')
    {
        iType = 1;
    }
    else if (strIdRangeList[0] == '-')
    {
        iType = 2;
    }
    else
    {
        CHECK_ERR(0, -1, "unknown type invalid strIDRangeList:{}", strIdRangeList);
    }

    std::string strIdRanges = strIdRangeList.substr(1, strIdRangeList.size() - 1);
    bool bContainId = false;
    iRetCode = CheckContainId(strIdRanges, iWorldId, bContainId);
    CHECK_ERR(0, iRetCode, "CheckContainID fail, strIDRanges:{}", strIdRanges);

    switch (iType)
    {
        case 1:
        {
            bContain = bContainId;
        }
        break;
        case 2:
        {
            bContain = !bContainId;
        }
        break;
        default:
        {
            CHECK_ERR(0, -1, "unknown type invalid strIDRangeList:{}", strIdRangeList);
        }
    }
    return 0;
}

int NFWelfareConfOne::CheckContainId(const std::string& strIdRangeList, int iWorldId, bool& bContain)
{
    bContain = false;
    if (strIdRangeList.empty())
    {
        bContain = true;
        return 0;
    }

    std::vector<std::string> vecStrIdRange;
    NFStringUtility::SplitString(strIdRangeList, ",", vecStrIdRange);
    if (vecStrIdRange.empty())
    {
        CHECK_ERR(0, -1, "invalid strIDRangeList:{}", strIdRangeList);
    }

    for (auto strIdRange : vecStrIdRange)
    {
        std::vector<int> intArray;
        NFStringUtility::SplitStringToVectorInt(strIdRange, "-", intArray);

        if (intArray.size() == 1)
        {
            if (intArray[0] == iWorldId)
            {
                bContain = true;
                return 0;
            }
        }
        else if (intArray.size() == 2)
        {
            if (iWorldId >= intArray[0] && iWorldId <= intArray[1])
            {
                bContain = true;
                return 0;
            }
        }
        else
        {
            CHECK_ERR(0, -1, "invalid strIDRangeList:{}", strIdRangeList);
        }
    }

    return 0;
}

int NFWelfareConfOne::CheckAndCalcOpenTimeRange(UnixTimeRange& stUnixTimeRangeOpen, const IntRange& stIntRangeGameOpen, uint32_t dwGameOpenDayBeginUnixSec, bool bIsIdip,
                                                const UnixTimeOne& startTimeGameSvrOpenDay, const UnixTimeOne& endTimeGameSvrOpenDay, int32_t iOpenTimeGameSvrOpenDayAdjustType, int32_t iCloseTimeGameSvrOpenDayAdjustType)
{
    uint32_t dwUnixSecBegin = 0;
    uint32_t dwUnixSecEnd = 0;
    if (stIntRangeGameOpen.m_iMin > 0)
    {
        uint64_t ullOpenBeginUnixSec = dwGameOpenDayBeginUnixSec + ((uint64_t)(stIntRangeGameOpen.m_iMin - 1) * SECONDS_ADAY);
        if (ullOpenBeginUnixSec > std::numeric_limits<uint32_t>::max())
        {
            CHECK_ERR(0, -1, "ullOpenBeginUnixSec:{} must <= {}", ullOpenBeginUnixSec, std::numeric_limits<uint32_t>::max());
        }
        if (iOpenTimeGameSvrOpenDayAdjustType == WELFARE_OPEN_TIME_GAME_SVR_OPEN_DAY_ADJUST_TYPE_WEEK_START)
        {
            if (NFTimeUtility::GetWeekDay127(ullOpenBeginUnixSec) != 1)
            {
                dwUnixSecBegin = NFTimeUtility::GetWeekStartTime(ullOpenBeginUnixSec + SECONDS_ADAY * 7) + startTimeGameSvrOpenDay.m_szTime_t;
            }
            else
            {
                dwUnixSecBegin = NFTimeUtility::GetWeekStartTime(ullOpenBeginUnixSec) + startTimeGameSvrOpenDay.m_szTime_t;
            }
        }
        else
        {
            dwUnixSecBegin = (uint32_t)(ullOpenBeginUnixSec + startTimeGameSvrOpenDay.m_szTime_t);
        }

        uint64_t ullOpenEndUnixSec = dwGameOpenDayBeginUnixSec + ((uint64_t)(stIntRangeGameOpen.m_iMax) * SECONDS_ADAY);
        if (ullOpenEndUnixSec > std::numeric_limits<uint32_t>::max())
        {
            CHECK_ERR(0, -1, "ullOpenEndUnixSec:{} must <= {}", ullOpenEndUnixSec, std::numeric_limits<uint32_t>::max());
        }

        if (iCloseTimeGameSvrOpenDayAdjustType == WELFARE_CLOSE_TIME_GAME_SVR_OPEN_DAY_ADJUST_TYPE_WEEK_END)
        {
            dwUnixSecEnd = NFTimeUtility::GetWeekEndTime(ullOpenEndUnixSec) + endTimeGameSvrOpenDay.m_szTime_t;
        }
        else
        {
            dwUnixSecEnd = (uint32_t)(ullOpenEndUnixSec + endTimeGameSvrOpenDay.m_szTime_t);
        }
    }
    else
    {
        dwUnixSecBegin = stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime_t;
        dwUnixSecEnd = stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime_t;
    }

    LOG_DEBUG(0, "open time with range:[{}:{}, {}:{}] DebugInfo stUnixTimeRangeOpen.m_stUnixTimeOneBegin[m_szTime_t:{} m_szTime:{}]"
              " stUnixTimeRangeOpen.m_stUnixTimeOneEnd[m_szTime_t:{} m_szTime:{}]"
              " stIntRangeGameOpen:[m_iMin:{} m_iMax:{}] dwGameOpenDayBeginUnixSec:{} bIsIDIP:{}"
              " startTimeGameSvrOpenDay:{} endTimeGameSvrOpenDay:{}"
              , dwUnixSecBegin, NFTimeUtility::DateTimeToStr(dwUnixSecBegin)
              , dwUnixSecEnd, NFTimeUtility::DateTimeToStr(dwUnixSecEnd)
              , stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime_t
              , stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime.ToString()
              , stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime_t
              , stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime.ToString()
              , stIntRangeGameOpen.m_iMin, stIntRangeGameOpen.m_iMax
              , dwGameOpenDayBeginUnixSec, bIsIdip
              , startTimeGameSvrOpenDay.m_szTime.ToString(), endTimeGameSvrOpenDay.m_szTime.ToString());

    if (dwUnixSecBegin >= dwUnixSecEnd)
    {
        CHECK_ERR(0, -1, "invalid open time with time range, begin:[{}:{}] must < end:[{}:{}]"
                  , dwUnixSecBegin, stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime.ToString()
                  , dwUnixSecEnd, stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime.ToString());
    }

    stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime_t = dwUnixSecBegin;
    stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime_t = dwUnixSecEnd;
    return 0;
}

int NFWelfareConfOne::CheckAndCalcShowTimeRange(UnixTimeRange& stUnixTimeRangeShow, const UnixTimeRange& stUnixTimeRangeOpen, bool bIsIdip)
{
    int iBeforeDay = 0;
    int iAfterDay = 0;

    UnixTimeRange stUnixTimeRangeShowOld = stUnixTimeRangeShow;

    iBeforeDay = NFCommon::strto<int>(stUnixTimeRangeShow.m_stUnixTimeOneBegin.m_szTime.ToString());
    if (iBeforeDay < 0)
    {
        CHECK_ERR(0, -1, "config before day:[{}], iBeforeDay:{}, must >= 0"
                  , stUnixTimeRangeShow.m_stUnixTimeOneBegin.m_szTime.ToString(), iBeforeDay);
    }

    iAfterDay = NFCommon::strto<int>(stUnixTimeRangeShow.m_stUnixTimeOneEnd.m_szTime.ToString());
    if (iBeforeDay < 0)
    {
        CHECK_ERR(0, -1, "config after day:[{}], iAfterDay:{}, must >= 0"
                  , stUnixTimeRangeShow.m_stUnixTimeOneEnd.m_szTime.ToString(), iBeforeDay);
    }

    uint32_t dwUnixSecBegin = stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime_t;
    uint64_t ullBeforeSec = (uint64_t)iBeforeDay * SECONDS_ADAY;
    if (ullBeforeSec >= dwUnixSecBegin)
    {
        stUnixTimeRangeShow.m_stUnixTimeOneBegin.m_szTime_t = 0;
    }
    else
    {
        stUnixTimeRangeShow.m_stUnixTimeOneBegin.m_szTime_t = (uint32_t)(dwUnixSecBegin - ullBeforeSec);
    }

    uint32_t dwUnixSecEnd = stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime_t;
    uint64_t ullAfterSec = (uint64_t)iAfterDay * SECONDS_ADAY;
    uint64_t ullEndUnixSec = dwUnixSecEnd + ullAfterSec;
    if (ullEndUnixSec >= std::numeric_limits<uint32_t>::max())
    {
        stUnixTimeRangeShow.m_stUnixTimeOneEnd.m_szTime_t = std::numeric_limits<uint32_t>::max();
    }
    else
    {
        stUnixTimeRangeShow.m_stUnixTimeOneEnd.m_szTime_t = (uint32_t)ullEndUnixSec;
    }

    LOG_DEBUG(0, "bIsIDIP:{} stUnixTimeRangeShowOld [Begin {} {} End {} {}] iBeforeDay:{} iAfterDay:{}"
              " stUnixTimeRangeOpen [Begin {} {} End {} {}] stUnixTimeRangeShow [Begin {} End {}]"
              , bIsIdip
              , stUnixTimeRangeShowOld.m_stUnixTimeOneBegin.m_szTime_t
              , stUnixTimeRangeShowOld.m_stUnixTimeOneBegin.m_szTime.ToString()
              , stUnixTimeRangeShowOld.m_stUnixTimeOneEnd.m_szTime_t
              , stUnixTimeRangeShowOld.m_stUnixTimeOneEnd.m_szTime.ToString()
              , iBeforeDay, iAfterDay
              , stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime_t
              , stUnixTimeRangeOpen.m_stUnixTimeOneBegin.m_szTime.ToString()
              , stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime_t
              , stUnixTimeRangeOpen.m_stUnixTimeOneEnd.m_szTime.ToString()
              , stUnixTimeRangeShow.m_stUnixTimeOneBegin.m_szTime_t
              , stUnixTimeRangeShow.m_stUnixTimeOneEnd.m_szTime_t);
    return 0;
}

int NFWelfareConfOne::SetConfData(uint64_t ullWelfareID, uint32_t dwChangeUnixSec, uint32_t dwGameOpenDayBeginUnixSec, int iWorldID)
{
    int iRetCode = 0;
    auto pWelfareDesc = WelfareDesc::Instance()->GetDesc(ullWelfareID);
    CHECK_NULL(ullWelfareID, pWelfareDesc);

    int iOldNodeNum = m_confOne.m_astWelfareNodeDesc.size();
    m_confOne.m_astWelfareNodeDesc.clear();
    for (int i = 0; i < (int)m_confOne.m_astWelfareNodeDesc.max_size(); ++i)
    {
        int iNodeId = i + 1;
        auto pNodeDesc = WelfareNodeDesc::Instance()->GetDescByWelfareIdNodeId(ullWelfareID, iNodeId);
        if (pNodeDesc == nullptr)
        {
            break;
        }
        m_confOne.m_astWelfareNodeDesc[iNodeId] = *pNodeDesc;
    }

    m_confOne.m_stWelfareDesc = *pWelfareDesc;

    LOG_DEBUG(ullWelfareID, "Load WorldID:{} ullWelfareID:{} Old NodeNum:{} ChangeUnixSec:{}:{}"
              " GameOpenDayBeginUnixSec:{}:{}"
              " Load End New iNodeNum:{}"
              , iWorldID, ullWelfareID, iOldNodeNum
              , dwChangeUnixSec, NFTimeUtility::DateTimeToStr(dwChangeUnixSec)
              , dwGameOpenDayBeginUnixSec, NFTimeUtility::DateTimeToStr(dwGameOpenDayBeginUnixSec)
              , m_confOne.m_astWelfareNodeDesc.size());

    // 校验本福利配置
    iRetCode = CheckAndCalcConf(dwGameOpenDayBeginUnixSec, false, iWorldID);
    CHECK_ERR(ullWelfareID, iRetCode, "CheckAndCalcConf");

    m_confOne.m_dwLastChangeUnixSec = dwChangeUnixSec;
    return 0;
}
